using System;
using System.Xml;

namespace FridayShopping.DataModel
{
	/// <summary>
	/// Stores data of a product either on the shopping list or in the main 
	/// product repository. Each product can belong to a single category by a key
	/// to that category.
	/// </summary>
	public class Product : ItemBase, ICloneable
	{
		private	int		amount;

		private int		purchased;

		private int		usual;

		private	float	price;

		private string	memo;

		private Key		categoryKey;

		#region Constructors
		public Product()
		{
		}

		public Product(Key categoryKey, string name, int amount) : base (name)
		{
			this.categoryKey = categoryKey;
			this.Amount = amount;
		}

		public Product(string line)
		{
			string[] parts = line.Split('\t');

			CategoryKey = new Key(int.Parse(parts[0]));
			Key = new Key(int.Parse(parts[2]));
			Name = parts[3];
			Amount = int.Parse(parts[4]);
		}

		#endregion

		#region Member Access
		public int Amount
		{
			get
			{
				return amount;
			}
			set 
			{
				amount = value;
			}
		}

		public int Purchased 
		{
			get
			{
				return purchased;
			}
			set
			{
				purchased = value;
			}
		}

		public float Price 
		{
			get
			{
				return price;
			}
			set
			{
				price = value;
			}
		}

		public int Usual
		{
			get
			{
				return usual;
			}
			set 
			{
				usual = value;
			}
		}

		public Key CategoryKey
		{
			get
			{
				return categoryKey;
			}
			set
			{
				categoryKey = value;
			}
		}

		public string Memo 
		{
			get
			{
				return memo;
			}
			set 
			{
				memo = value;
			}
		}
		#endregion

		#region Shopping List operations (Buy, Return, Is completed etc..)
		public void TakeOne()
		{
			if (Purchased < Amount) 
			{
				Purchased++;
			}
		}

		public void ReturnOne()
		{
			if (Purchased > 0)
			{
				Purchased--;
			}
		}

		public void TakeAll()
		{
			Purchased = Amount;
		}

		public void ReturnAll()
		{
			Purchased = 0;
		}

		public void UpdateAmounts() 
		{
			Amount = Amount - Purchased;
			Purchased = 0;
		}

		public bool PurchaseComplete
		{
			get 
			{
				return (Amount == Purchased);
			}
		}

		public void SetAmountAsUsual()
		{
			if (Usual >= 0) 
			{
				Amount = Usual;
			}
		}

		#endregion

		#region IClonable Implementation
		public object Clone()
		{
			Product obj = new Product();

			obj.Key = Key;
			obj.Name = Name;
			obj.Price = Price;
			obj.Amount = Amount;
			obj.Purchased = Purchased;
			obj.CategoryKey = CategoryKey;

			return obj;
		}
		#endregion

		#region Serialization / Deserialization
		protected override void SerializeMembers(System.Xml.XmlTextWriter xmlWriter)
		{
			base.SerializeMembers (xmlWriter);

			// Notice the order
			xmlWriter.WriteElementString("Amount", XmlConvert.ToString(Amount));
			xmlWriter.WriteElementString("Purchased", XmlConvert.ToString(Purchased));
			xmlWriter.WriteElementString("Price", XmlConvert.ToString(Price));
			xmlWriter.WriteElementString("Usual", XmlConvert.ToString(Usual));
			CategoryKey.Serialize(xmlWriter,"CategoryKey");
			xmlWriter.WriteElementString("Memo", Memo);
		}

		public override void DeserializeMembers(XmlNodeReader xmlReader)
		{
			base.DeserializeMembers (xmlReader);
			
			// The read order must match the write order
			if (xmlReader.IsStartElement("Amount")) 
			{
				Amount = XmlConvert.ToInt32(xmlReader.ReadElementString());
			}
			if (xmlReader.IsStartElement("Purchased")) 
			{
				Purchased = XmlConvert.ToInt32(xmlReader.ReadElementString());
			}
			if (xmlReader.IsStartElement("Price")) 
			{
				Price = XmlConvert.ToSingle(xmlReader.ReadElementString());
			}
			if (xmlReader.IsStartElement("Usual"))
			{
				Usual = XmlConvert.ToInt32(xmlReader.ReadElementString());
			}
			if (xmlReader.IsStartElement("CategoryKey"))
			{
				CategoryKey = Key.DeserializeMembers(xmlReader);
			}
			if (xmlReader.IsStartElement("Memo"))
			{
				Memo = xmlReader.ReadElementString();
			}
		}
		#endregion

	}


	/// <summary>
	/// Holds a list of products each item is of the type 'Product'
	/// </summary>
	[ListItemType(typeof(Product))]
	public class Products : ItemListBase 
	{
		#region Constructor
		public Products()
		{
		}
		#endregion
	}
}
